#include "Ctrl.h"

#if IteratorPattern_

#include <vector>

typedef typename string object;

template<class Item>
class Iterator
{
public :
	Iterator(){}
	virtual ~Iterator(){}
	virtual void First() = 0;
	virtual void Next() = 0;
	virtual bool IsDone() = 0;
	virtual Item* CurrentItem() = 0;
};

template<class Item>
class Aggregate
{
public:
	Aggregate(){}
	~Aggregate(){}
	virtual size_t GetSize() = 0;
	virtual void push(Item item) = 0;
	virtual Item* at(const size_t nIndex) = 0;
	virtual Iterator<Item>* CreateIterator() = 0;
};

template<class Item>
class ConcreteIterator;

template<class Item>
class ConcreteAggregate : public Aggregate<Item>
{
private:
	vector<Item> m_data;
public:
	ConcreteAggregate(){}
	virtual ~ConcreteAggregate(){}
	virtual size_t GetSize() {
		return m_data.size();
	}
	virtual void push(Item item) {
		m_data.push_back(item);
	}
	virtual Item* at(const size_t nIndex) {
		return &m_data[nIndex];
	}
	virtual Iterator<Item>* CreateIterator() {
		return new ConcreteIterator<Item>(this);
	}
};

template<class Item>
class ConcreteIterator : public Iterator<Item>
{
private:
	ConcreteAggregate<Item>* m_aggregate;
	size_t m_current;
public:
	ConcreteIterator(ConcreteAggregate<Item>* _aggregate):m_aggregate(_aggregate), m_current(0) {}
	~ConcreteIterator(){}

	virtual void First() override {
		m_current = 0;
	}

	virtual void Next() override {
		if (m_current < m_aggregate->GetSize()) {
			++m_current;
		}
	}
	virtual bool IsDone() override {
		return m_current >= m_aggregate->GetSize();
	}
	virtual Item* CurrentItem() override {
		if (m_current < m_aggregate->GetSize()) {
			return (m_aggregate->at(m_current));
		}
		else {
			return NULL;
		}
	}

};


int main(int argc, char* argv[])
{


	printf("Templete is int.\n");
	Aggregate<int>* aggr = new ConcreteAggregate<int>;
	int num = 3;
	aggr->push(num--);
	aggr->push(num--);
	aggr->push(num--);
	Iterator<int>* iter = aggr->CreateIterator();
	for (iter->First(); !iter->IsDone(); iter->Next())
	{
		printf("Num is %d .\n", *(iter->CurrentItem()));
	}

	printf("Templete is float.\n");
	Aggregate<float>* aggr1 = new ConcreteAggregate<float>;
	float num1 = 9;
	aggr1->push(num1--);
	aggr1->push(num1--);
	aggr1->push(num1--);
	Iterator<float>* iter1 = aggr1->CreateIterator();
	for (iter1->First(); !iter1->IsDone(); iter1->Next())
	{
		printf("Num is %f .\n", *(iter1->CurrentItem()));
	}

}





#endif